import type {
	Workflow,
	WorkflowOption,
	FlCallback,
	WorkflowInfo,
	WorkComponent,
	StepState,
	WorkflowStates
} from "./type";
import BasicWorkflowVue from "./basic-workflow.vue";
import { createVNode } from "vue";
import {
	setWorkflowDefaultOption,
	updateComponentInfo,
	updateWorkflowNewData
} from "./utils";

type WT<P> = Workflow<P, keyof P>;

const defaultOption: WorkflowOption = {
	activeColor: "#f99",
	noActiveColor: "#344",
	showSteps: true
};

export class BasicWorkflow<P extends Record<string, WorkComponent>> {
	/** 组件实例 */
	private workflowInstance: any = {};
	/** 工作流程记录 (添加数据记录) */
	private workflowList: WT<P>[] = [];
	/** 初始数据 */
	private workflowDefaultData = {} as Record<keyof P, any>;
	/** 最新数据集合 */
	private workflowNewData = {} as Record<keyof P, any>;
	/** 步骤整体配置 */
	private option: WorkflowOption = defaultOption;
	/** 上一步切换前回调 */
	private prevCallbacks: FlCallback<P>[] = [];
	/** 下一步切换前回调 */
	private nextCallbacks: FlCallback<P>[] = [];
	/** 步骤切换完毕的回调 */
	private changeCallbacks: FlCallback<P>[] = [];
	/** 当前步数 */
	private currentStepNum: number = 0;

	/** 查询索引 */
	private findWorkflowIndex(targetKey: string) {
		return this.workflowList.findIndex((wl) => wl.key === targetKey);
	}
	/** 查询对象 */
	private findWorkflows(targetKey: string) {
		return this.workflowList.find((wl) => wl.key === targetKey);
	}

	/** 创建步骤信息 */
	private createInfo(
		key: keyof P,
		step: number,
		toStep: number,
		state: StepState
	): WorkflowInfo<P> {
		let toData = null;
		if (toStep !== -1)
			toData = this.workflowNewData[this.workflowList[toStep].key];
		return {
			currentData: this.workflowNewData[key],
			currentStep: step,
			toStep,
			toData,
			stepState: state,
			key
		};
	}

	/** 更新步骤返回对应信息 */
	private updateCurrentStepNum(state: "prev" | "next"): WorkflowInfo<P> {
		const key = this.workflowList[this.currentStepNum].key;
		// 起始位 直接返回
		if (this.currentStepNum === 0 && state === "prev") {
			return this.createInfo(key, 0, -1, "start");
		} else if (
			this.currentStepNum === this.workflowList.length - 1 &&
			state === "next"
		) {
			// 终止位 直接返回
			let lastIdx = this.workflowList.length - 1;
			return this.createInfo(key, lastIdx, -1, "end");
		}
		// 保留原步骤后 更新步骤
		let currentStep = this.currentStepNum;
		if (state === "next") ++this.currentStepNum;
		if (state === "prev") --this.currentStepNum;
		return this.createInfo(
			this.workflowList[currentStep].key,
			currentStep,
			this.currentStepNum,
			"afoot"
		);
	}

	/** 注册上一步切换前回调 */
	onPrevSteps(callback: FlCallback<P>) {
		this.prevCallbacks.push(callback);
	}
	/** 下一步切换前回调 */
	onNextSteps(callback: FlCallback<P>) {
		this.nextCallbacks.push(callback);
	}
	/** 步骤切换完毕的回调 */
	onChangeSteps(callback: FlCallback<P>) {
		this.changeCallbacks.push(callback);
	}

	/** 添加 */
	addWorkflow<K extends keyof P>(workflow: Workflow<P, K>) {
		const key = workflow.key as string;
		const idx = this.findWorkflowIndex(key);
		if (idx === -1) {
			/** 设置配置默认值 */
			this.workflowList.push(setWorkflowDefaultOption(workflow));
			/** 设置数据 */
			updateWorkflowNewData(
				workflow,
				this.workflowNewData,
				this.workflowDefaultData,
				true
			);
		} else console.error(key + "重复添加");
	}
	/** 删除 */
	removeWorkflow(key: string) {
		const idx = this.findWorkflowIndex(key);
		if (idx > -1) {
			this.workflowList.splice(idx, 1);
			Reflect.deleteProperty(this.workflowNewData, key);
		} else console.error(key + "没有被注册");
	}

	/** 上下一步变化时 */
	private change(state: "prev" | "next") {
		if (!this.workflowList.length)
			return console.error("请使用 addWorkflow 注册工作流程");
		const info = this.updateCurrentStepNum(state);

		/** 回调事件监听 */
		if (state === "next")
			this.nextCallbacks.forEach((fn) => fn(info, this.workflowNewData));
		else this.prevCallbacks.forEach((fn) => fn(info, this.workflowNewData));

		/** 点击切换时缓存当前页面数据 */
		updateWorkflowNewData(
			this.findWorkflows(info.key as string)!,
			this.workflowNewData
		);

		/** 更新即将渲染的组件数据 */
		if (info.toStep !== -1) {
			updateComponentInfo(this.workflowList[info.toStep], info.toData);
		}

		/** 更新props */
		this.workflowInstance.component?.exposed.setProps({
			currentStepNum: this.currentStepNum
		});
	}

	// /** 操作状态 key 为 all 修改所有步骤信息 */
	setState(key: string | "all", option: WorkflowStates): void {
		if (key === "all") {
			this.workflowList.forEach((work) => {
				work.workflowState = { ...work.workflowState, ...option };
			});
		}
		const target = this.findWorkflows(key as string)!;
		target.workflowState = { ...target.workflowState, ...option };
	}
	getState(key: string): WorkflowStates {
		return this.findWorkflows(key as string)!.workflowState!;
	}

	setOption(option: WorkflowOption): void {
		this.option = { ...this.option, ...option };
	}
	getOption(): WorkflowOption {
		return this.option;
	}

	// /** 清空指定步骤对应的数据 all 为清理全部的 */
	reset(key: keyof P | "all"): void {
		if (key === "all") {
			this.workflowList.forEach((work) => {
				updateComponentInfo(work, this.workflowDefaultData[work.key]);
			});
		}
		updateComponentInfo(
			this.findWorkflows(key as string)!,
			this.workflowDefaultData[key]
		);
	}

	getVNode() {
		this.workflowInstance = createVNode(BasicWorkflowVue, {
			configture: {
				currentStepNum: this.currentStepNum,
				globalOption: this.option,
				workflowList: this.workflowList
			},
			onPrev: () => this.change("prev"),
			onNext: () => this.change("next")
		});

		return this.workflowInstance;
	}
}
